package three;

import java.lang.reflect.Constructor;
import java.util.Iterator;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;

/**
 * 动态MBean是在运行期才定义它的属性和方法，也就是说它有什么属性和方法是可以动态改变的。
 * 动态MBean主要利用一些辅助类（构造函数类MBeanConstructorInfo、属性类MBeanAttributeInfo、方法类MBeanOperationInfo）来完成这个功能，
 * 所有的动态MBean必须实现DynamicMBean接口。
 * 
 * 
 * 实例：给出一个动态MBean的实例，这个实例最初动态构了一个Name属性及一个print方法，当我们执行它的print方法之后，又给此MBean新增了一个print1方法
 * 
 * setAttribute设置属性、getAttribute取得属性、setAttributes设置一组属性、getAttributes取得一组属性、
 * invoke方法调用、           getMBeanInfo MBeanServer由这个方法得到关键的MBean类的构造信息。
 */
public class HelloDynamic implements DynamicMBean {
	
	private String name;
	private MBeanInfo mBeanInfo = null;
	private String className;
	private String description;
	private MBeanAttributeInfo[] attributes;
	private MBeanConstructorInfo[] constructors;
	private MBeanOperationInfo[] operations;
	MBeanNotificationInfo[] mBeanNotificationInfoArray;
	
	public HelloDynamic(){
		init();
		buildDynamicMBean();
	}
	
	private void init(){
		className = this.getClass().getName();
		name="xxxxx";
		description = "一个简单的动态MBean实现";
		attributes = new MBeanAttributeInfo[1];
		constructors = new MBeanConstructorInfo[1];
		operations = new MBeanOperationInfo[1];
		mBeanNotificationInfoArray = new MBeanNotificationInfo[0];
	}
	
	private void buildDynamicMBean(){
		//设定构造函数
		@SuppressWarnings("rawtypes")
		Constructor[] thisconstructors = this.getClass().getConstructors();
		                                          	//description                                       constructor
		constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", thisconstructors[0]);
		
		//设定属性                                                                                                 name      type                  description  isRead  isWrite isIs
		attributes[0] = new MBeanAttributeInfo("Name", "java.lang.String", name, true,true,false);
		
		MBeanParameterInfo[] params = null;
		                                      // name     description                    type         impcat
		operations[0] = new MBeanOperationInfo("print", "print():print the name",params,"void",MBeanOperationInfo.INFO);
		mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);
	}
	
	/**
	 * 动态添加一个print1方法
	 */
	public void dynamicAddOperation(){
		init();
		operations = new MBeanOperationInfo[2];
		//初始化第一个方法print
		this.buildDynamicMBean();
		operations[1] = new MBeanOperationInfo("print1","print1(): print the name",null,"void",MBeanOperationInfo.INFO);
		mBeanInfo = new MBeanInfo(className,description,attributes,constructors,operations,mBeanNotificationInfoArray);
		
	}

	@Override
	public Object getAttribute(String attributeName) 
			throws AttributeNotFoundException, MBeanException, ReflectionException {
		if(attributeName == null)
			return null;
		if("Name".equals(attributeName))
			return name;
		return null;
	}

	@Override
	public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException,
			MBeanException, ReflectionException {
		if(attribute == null){
			return;
		}
		String Name = attribute.getName();
		Object value = attribute.getValue();
		try {
			if(Name.equals("Name")){
				if(value == null){
					name = null;
				}else if((Class.forName("java.lang.String")).isAssignableFrom(value.getClass())){
					name = (String)value;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public AttributeList getAttributes(String[] attributeNames) {
		if(attributeNames == null)
			return null;
		AttributeList resultList = new AttributeList();
		for(int i = 0; i < attributeNames.length; i++){
			try {
				Object value = this.getAttribute(attributeNames[i]);
				resultList.add(new Attribute(attributeNames[i], value));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return resultList;
	}

	@Override
	public AttributeList setAttributes(AttributeList attributes) {
		if(attributes == null)
			return null;
		AttributeList resultList = new AttributeList();
		if(attributes.isEmpty())
			return resultList;
		for(@SuppressWarnings("rawtypes")Iterator it = attributes.iterator(); it.hasNext();){
			Attribute attr = (Attribute) it.next();
			try {
				this.setAttribute(attr);
				String name = attr.getName();
				Object value = this.getAttribute(name);
				resultList.add(new Attribute(name,value));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return resultList;
	}

	@Override
	public Object invoke(String operationName, Object[] params, String[] signature) 
			throws MBeanException, ReflectionException {
		if(operationName.equals("print")){//当执行print的时候，动态添加一个print1方法
			this.dynamicAddOperation();
			return null;
		}else if(operationName.equals("print1")){
			System.out.println("这是动态增加的一个方法:print1");
			return null;
		}else{
			throw new ReflectionException(new NoSuchMethodException(operationName),
					"Cannot find the operation " + operationName + " in " + className);
		}
	}

	@Override
	public MBeanInfo getMBeanInfo() {
		return mBeanInfo;
	}

}
